#ifndef __SHMIPC_COM_UDS_CLIENT_H__
#define __SHMIPC_COM_UDS_CLIENT_H__

#include <cstdint>
#include <string>
#include <functional>
#include <map>
#include <atomic>

#include "shmipc/core/core_types.h"
#include "shmipc/core/xresult.h"
#include "shmipc/core/xthread.h"
#include "shmipc/com/xmessage.h"
#include "shmipc/com/xmessage_allocator.h"
#include "shmipc/com/internal/uds_session.h"

namespace shmipc::com {

class UdsClient: virtual public XMessageAllocator  {
public:
    using OnConnectStatusHandler = std::function<void(bool is_connected)>;
    using OnMessageHandler = std::function<void(XMessageSp)>;
    using IoWorker = std::unique_ptr<core::XThread>;
    using MessageHandlerMap = std::map<SequenceNumber, OnMessageHandler>;
    using MessageMap = std::map<uint8_t, MessageHandlerMap>; /** uint8_t: XMessageType */
public:
    UdsClient();
    virtual ~UdsClient();

public:
    virtual core::XResultCode connect(const std::string& url, OnConnectStatusHandler on_handler = nullptr);
    virtual core::XResultCode disconnect();
    virtual bool is_connected();
    virtual core::XResultCode setOnMessageHandler(OnMessageHandler on_event_handler);
public:
    virtual core::XResult<XMessageSp> request(XMessageSp param, int32_t timeout_ms = core::WaitType::WaitForever);
    virtual core::XResultCode requestAsync(XMessageSp param, OnMessageHandler on_response_handler = nullptr);

protected:
    virtual void onMessage(XMessageSp msg); //Messages outside of request/requestAsync; e.g the event from server


protected:
    virtual OnMessageHandler popMsgHandler(uint8_t type, SequenceNumber seq_num);
    virtual uint16_t generate_seq_num();
protected:
    std::atomic_uint16_t next_seq_num_ = 0;
    bool is_connected_ = false;
    bool is_running_ = false;
    
    internal::UdsSessionSp uds_session_ = nullptr;
    OnMessageHandler on_message_handler_;
    OnConnectStatusHandler on_connect_status_;
    MessageMap on_response_map_;
};


} //namespace shmipc::com

#endif /** !__SHMIPC_COM_UDS_CLIENT_H__ */
